/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */

/**
 * @version conn.h 0.0.1
 * @package Comoro
 * @author Dr.NP <np@bsgroup.org>
 * 
 * Network connection service handler header
 */

#include <arpa/inet.h>
#include <event.h>

// Server consts

#define MAX_CLIENT								102400
#define MAX_SEND_TIME							10
#define MAX_SEQ_RESEND							32
#define CMD_SIZE									32
#define ADMIN_IP									"127.0.0.1"

#define MAX_CLIENT_RUNNER						16
#define MAX_RUNNER_GROUP							8

#define TCP_TIMEOUT								10
#define SEQ_BUFFER_SIZE							64

#define SERVER_POOL_SIZE							1024
#define CLIENT_POOL_BASE_SIZE					1024
#define CONNECTOR_POOL_SIZE						1024

#define CLIENT_READ_BUFFER_SIZE					4096
#define CLIENT_READ_BUFFER_SIZE_HIGHWAT		262144
#define CONNECTOR_READ_BUFFER_SIZE				4096
#define CONNECTOR_READ_BUFFER_SIZE_HIGHWAT	1048576

// Sequence item
struct sequence_item
{
	unsigned int seq_id;
	char *seq_str;
	int msglen;
	char sgn;
};

// Connection client
struct conn_client
{
	// Socket informations
	int id;
	int client_fd;
	int server_id;
	unsigned long client_addr;
	int client_port;
	unsigned int conn_time;
	unsigned int last_hb_time;
	unsigned int last_rcv_id;
	unsigned int last_snd_id;
	struct sequence_item *seq_buffer[SEQ_BUFFER_SIZE];
	struct event ev_read;
	char *read_buffer;
	unsigned int buffer_size;
	unsigned int buffer_data_size;
	int runner_id;
};

// Connection server struct
struct conn_server
{
	int id;
	int listen_fd;
	struct sockaddr_in listen_addr;
	unsigned long srv_addr;
	int srv_port;
	unsigned int start_time;
	int listen_queue_length;
	int nonblock;
	int tcp_send_buffer_size;
	int tcp_recv_buffer_size;
	int tcp_timeout;
	int tcp_reuse;
	int tcp_nodelay;
	struct event ev_accept;
	void (* on_data_callback) (int, void *, unsigned int);
	void (* on_conn_callback) (int);
	void (* on_close_callback) (int);
};

// Connector to server
struct conn_connector
{
	int id;
	int connect_fd;
	struct sockaddr_in connect_addr;
	unsigned long srv_addr;
	int srv_port;
	int nonblock;
	int tcp_send_buffer_size;
	int tcp_recv_buffer_size;
	int tcp_nodelay;
	unsigned int conn_time;
	unsigned int last_hb_time;
	unsigned int last_rcv_id;
	unsigned int last_seq_id;
	struct sequence_item *seq_buffer[SEQ_BUFFER_SIZE];
	struct event ev_read;
	char *read_buffer;
	unsigned int buffer_size;
	unsigned int buffer_data_size;
	void (* on_data_callback) (void *, unsigned int);
	void (* on_conn_callback) ();
	void (* on_close_callback) ();
};

/* BEGIN OF FUNCTION DEFINE */
int conn_init										();
int conn_close									();
int conn_setnonblock								(int);

int conn_tcp_server_new							(struct conn_server *);
void conn_tcp_server_accept						(int, short, void *);
int conn_tcp_server_free							(struct conn_server *);
void conn_tcp_server_on_data					(int, short, void *);

struct conn_client * conn_client_new			(int);
int conn_client_clear							(struct conn_client *);
int conn_client_free								(struct conn_client *);
int conn_client_send								(struct conn_client *, const char *, int);
void conn_client_hb								(struct conn_client *);
void conn_client_hb_dt							(void *);
void conn_client_rcv_seq_set					(struct conn_client *, unsigned int);
unsigned int conn_client_rcv_seq_get			(struct conn_client *);
void conn_client_snd_seq_set					(struct conn_client *, unsigned int);
unsigned int conn_client_snd_seq_get			(struct conn_client *);
unsigned int conn_client_seq_add				(struct conn_client *, char *, int);
void conn_client_seq_send						(struct conn_client *, unsigned int);
void conn_client_seq_del							(struct conn_client *, unsigned int);
int conn_client_seq_flush						(struct conn_client *);
void conn_client_seq_flush_all					(void *);

int conn_tcp_connector_new						(struct conn_connector *);
int conn_tcp_connector_send						(struct conn_connector *, const char *, int);
int conn_tcp_connector_free						(struct conn_connector *);
void conn_tcp_connector_on_data					(int, short, void *);
void conn_tcp_connector_hb						(void *);

int conn_server_list_find_free					();

int conn_client_list_init						();
int conn_client_list_enlarge					();
int conn_client_list_purge						();
int conn_client_list_find_free					();
struct conn_client * conn_client_list_get		(int);
int conn_client_list_count						();
int conn_client_list_max							();
int conn_client_list_size						();

int conn_connector_list_find_free				();
/* END OF FUNCTION DEFINE */
